package com.lfy.encrypt;




import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Security;
import java.util.Arrays;
import java.util.Base64;
import java.util.Random;


/**
 * AES算法
 * @author 杨
 *
 */
public class AESUtil {


    //public static final String VIPARA =  2015050120150601
    public static final String VIPARA = "authorlvfeiyangs";

    public static final String bm = "utf-8";


    /**
     * 加密
     * @param source	源字符串
     * @param password  密码
     *
     */
    public static byte[] encrpt(String source,String password) throws Exception
    {
        IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
        SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);
        byte[] result = cipher.doFinal(source.getBytes(bm));
        return result;
    }
    /**
     * 解密
     * @param content   目标字符串
     * @param password  密码
     *
     * @throws Exception
     */
    public static String decrypt(byte[] content, String password) throws Exception
    {
        IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
        SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");// 创建密码器
        cipher.init(Cipher.DECRYPT_MODE, key,zeroIv);// 初始化
        byte[] result = cipher.doFinal(content);
        return new String(result,bm);
    }

    public static String encrptString(String source,String password) throws Exception
    {

        byte[] result = encrpt(source,password);
        return Base64.getEncoder().encodeToString(result);
    }
    public static String decryptString(String source,String password) throws Exception
    {
        byte[] result = Base64.getDecoder().decode(source);
        return decrypt(result,password);
    }

    /**
     * 将字符串解出
     * @param v
     * @param password
     *
     */
    public static String decryptByString(String v,String password) throws Exception
    {
        return decrypt(HashUtils.toBytes(v),password);
    }
    /**
     * 生成随即密码
     * @param pwd_len 生成的密码的总长度
     *   密码的字符串
     */
    public static String genRandomNum(int pwd_len){
        //35是因为数组是从0开始的，26个字母+10个数字
        final int  maxNum = 36;
        int i;  //生成的随机数
        int count = 0; //生成的密码的长度
        char[] str = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
                'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
                'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

        StringBuffer pwd = new StringBuffer("");
        Random r = new Random();
        while(count < pwd_len){
            //生成随机数，取绝对值，防止生成负数，
            i = Math.abs(r.nextInt(maxNum));  //生成的数最大为36-1
            if (i >= 0 && i < str.length) {
                pwd.append(str[i]);
                count ++;
            }
        }

        return pwd.toString();
    }
    public static String hexToUtf8String(String hex) {
        byte[] bytes = new byte[hex.length() / 2];
        for (int i = 0; i < hex.length(); i += 2) {
            bytes[i / 2] = (byte) Integer.parseInt(hex.substring(i, i + 2), 16);
        }
        return new String(bytes, StandardCharsets.UTF_8);
    }
       /*   //创建AES，指定秘钥字节数组
        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        // 加密操作
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] plainText = "Hello, World!".getBytes(StandardCharsets.UTF_8);
        //使用AES加密
        byte[] encryptedText = cipher.doFinal(plainText);
        // 将加密后的字节数组转换为Base64编码的字符串
        String encryptedTextBase64 = Base64.getEncoder().encodeToString(encryptedText);
        // 解密操作
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        //将加密后的Base64编码的字符串转换为字节数组,并解密
        byte[] decryptedText = cipher.doFinal(Base64.getDecoder().decode(encryptedTextBase64));
        System.out.println("原来 Text: " + new String(plainText, StandardCharsets.UTF_8));
        System.out.println("秘钥: "+hexKey);
        System.out.println("秘钥字节数组："+ Arrays.toString(keyBytes));
        System.out.println("加密后 Text (Base64)前: "+Arrays.toString(encryptedText));
        System.out.println("加密后 Text (Base64):后 " + encryptedTextBase64);
        System.out.println("解密后 Text: " + new String(decryptedText, StandardCharsets.UTF_8));*/
// 新增的函数，用于将十六进制字符串转换为字节数组
       private static byte[] hexStringToByteArray(String s) {
           int len = s.length();
           byte[] data = new byte[len / 2];
           for (int i = 0; i < len; i += 2) {
               data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                       + Character.digit(s.charAt(i+1), 16));
           }
           return data;
       }
    public static void main(String[] args) throws Exception {

        test();

    }

    public static void test() throws Exception {
        //16进制字符串秘钥
        String hexKey = "65839B543BB54BBCBA8301A79224416F";
        //将16进制字符串转换为字节数组
//        byte[] keyBytes = Files.readAllBytes(Paths.get("F:\\65839B543BB54BBCBA8301A79224416F.key"));
        String[] hexStrings = {
                "01", "96", "78", "69", "94", "a0", "b2", "36",
                "e3", "b1", "ec", "b2", "b3", "1c", "be", "f8",
                "37", "f0", "a4", "d9", "95", "6f", "03", "a5",
                "4d", "56", "76", "cf", "38", "43", "80", "4b"
        };

        byte[] keyBytes = new byte[hexStrings.length];
        for (int i = 0; i < hexStrings.length; i++) {
            keyBytes[i] = (byte) Integer.parseInt(hexStrings[i], 16);
        }

        System.out.println("key长度："+keyBytes.length);
        String ivHex = "033B5906189C49A1A7E255B6C75A5EAB";
        byte[] ivBytes = hexStringToByteArray(ivHex);

        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

        for (int i = 0; i <= 743; i++) {
            String inputFilePath = "C:\\Users\\吕飞扬\\Desktop\\fsdownload\\tmp\\video_1721006952536_" + i + ".ts";
            String outputFilePath = "E:\\pcjm\\decrypted_video_" + i + ".ts";

            try (FileInputStream fis = new FileInputStream(inputFilePath);
                 FileOutputStream fos = new FileOutputStream(outputFilePath)) {

                byte[] buffer = new byte[1024];
                int bytesRead;

                while ((bytesRead = fis.read(buffer)) != -1) {
                    byte[] decryptedBytes = cipher.update(buffer, 0, bytesRead);
                    if (decryptedBytes != null) {
                        fos.write(decryptedBytes);
                    }
                }


                byte[] finalDecryptedBytes = cipher.doFinal();
                if (finalDecryptedBytes != null) {
                    fos.write(finalDecryptedBytes);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //合并
        String finalVideoPath = "E:\\finalpc\\final_video.ts";

        try (FileOutputStream fos = new FileOutputStream(finalVideoPath)) {
            for (int i = 0; i <= 743; i++) {
                String decryptedFilePath = "E:\\pcjm\\decrypted_video_" + i + ".ts";

                try (FileInputStream fis = new FileInputStream(decryptedFilePath)) {
                    byte[] buffer = new byte[1024];
                    int bytesRead;

                    while ((bytesRead = fis.read(buffer)) != -1) {
                        fos.write(buffer, 0, bytesRead);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}